﻿using pdftron.PDF;
using pdftron.SDF;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236

namespace CompleteReader.DocumentsPageDialogs
{
    public sealed partial class PackageDialog : UserControl
    {
        private class PackageItem
        {
            public string FileName;
            public bool IsPDF;
            
            public PackageItem(string fileName, bool isPDF)
            {
                this.FileName = fileName;
                this.IsPDF = isPDF;
            }
        }

        private bool _ErrorHappened;
        private string _ErrorMessage;
        private int filesOpened = 0;

        private StorageFile _SelectedFile;
        private IRandomAccessStream _SelectedStream;

        private IList<StackPanel> _PackageNestingStack;

        private PDFDoc _PDFDoc;
        public PDFDoc PDFDoc
        {
            set 
            { 
                _PDFDoc = value;
                if (_PDFDoc != null)
                {
                    _PackageNestingStack.Clear();
                    ContentScroller.Content = null;
                    ContentScroller.Content = CreateItemStack(_PDFDoc);
                    CurrentPackageName.Text = System.IO.Path.GetFileName(_PDFDoc.GetFileName());
                    DeleteAllTemporaryPackagePDFs();
                }
            }
        }

        public delegate void OnFileSelectedHandler(PDFDoc doc, bool err, string errorMessage);
        public event OnFileSelectedHandler FileSelcted;
        
        public PackageDialog()
        {
            this.InitializeComponent();
            _PackageNestingStack = new List<StackPanel>();
        }

        private void BackButton_Click(object sender, RoutedEventArgs e)
        {
            if (_PackageNestingStack.Count == 0)
            { 
                if (FileSelcted != null)
                {
                    FileSelcted(null, false, null);
                }
            }
            else
            {
                PopFromStack();
            }
        }

        private async void DeleteAllTemporaryPackagePDFs()
        {
            StorageFolder folder = await GetPDFPackageFolderAsync();

            IReadOnlyList<Windows.Storage.StorageFile> allFiles = await folder.GetFilesAsync();
            foreach (Windows.Storage.StorageFile file in allFiles)
            {
                System.Diagnostics.Debug.WriteLine(file.Path);
                System.Diagnostics.Debug.WriteLine("Extension: " + System.IO.Path.GetExtension(file.Path));
                System.Diagnostics.Debug.WriteLine("Has extension? " + System.IO.Path.HasExtension(file.Path));
                if (System.IO.Path.HasExtension(file.Path) && System.IO.Path.GetExtension(file.Path).Equals(".temporary_pdf"))
                {
                    try
                    {
                        await file.DeleteAsync();
                    }
                    catch (Exception e)
                    {
                        System.Diagnostics.Debug.WriteLine("Error deleting file: " + e.Message);
                    }
                }
            }
            
        }

        #region Construct Content


        private StackPanel CreateItemStack(PDFDoc doc)
        {
            StackPanel itemStack = new StackPanel();

            IList<PackageItem> items = GetPackageContent(doc);
            foreach (PackageItem item in items)
            {
                Button button = new Button();
                button.Click += ItemButton_Click;
                button.Tag = item;
                itemStack.Children.Add(button);

                TextBlock contentBlock = new TextBlock();
                contentBlock.Text = item.FileName;
                button.Content = contentBlock;
            }
            return itemStack;
        }




        private IList<PackageItem> GetPackageContent(PDFDoc doc)
        {
            List<PackageItem> items = new List<PackageItem>();

            NameTree files = NameTree.Find(doc.GetSDFDoc(), "EmbeddedFiles");
            if (files.IsValid())
            {
                NameTreeIterator nameTreeIterator = files.GetIterator();
                while (nameTreeIterator.HasNext())
                {
                    String entryName = nameTreeIterator.Key().GetAsPDFText();
                    bool isPDF = false;
                    if (HasExtension(entryName))
                    {
                        string extension = GetExtension(entryName);
                        if (extension.Equals("pdf", StringComparison.OrdinalIgnoreCase))
                        {
                            isPDF = true;
                        }
                    }
                    items.Add(new PackageItem(entryName, isPDF));
                    nameTreeIterator.Next();
                }
            }
            return items;
        }

        private async System.Threading.Tasks.Task<PDFDoc> ExtractPDFDocFromPortFolio(PDFDoc doc, string fileName)
        {
            try
            {
                StorageFolder folder = await GetPDFPackageFolderAsync();
                NameTree files = NameTree.Find(doc.GetSDFDoc(), "EmbeddedFiles");
                if (files.IsValid()) {
                    // Traverse the list of embedded files.
                    NameTreeIterator nameTreeIterator = files.GetIterator();
                    while (nameTreeIterator.HasNext()) {
                        String entryName = nameTreeIterator.Key().GetAsPDFText();
                        if (entryName.Equals(fileName, StringComparison.OrdinalIgnoreCase)) {
                        
                            pdftron.PDF.FileSpec fileSpec = new pdftron.PDF.FileSpec(nameTreeIterator.Value());
                            pdftron.Filters.IFilter filter = fileSpec.GetFileData();
                            if (filter != null) {
                                string newFileName = System.IO.Path.Combine(folder.Path, "mynewfile.temporary_pdf");
                                filesOpened++;
                                filter.WriteToFile(newFileName, false);
                                _SelectedFile = await folder.GetFileAsync("mynewfile.temporary_pdf");
                                _SelectedStream = await _SelectedFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
                                PDFDoc newDoc = new PDFDoc(_SelectedStream);
                                return newDoc;
                            }
                        }
                        nameTreeIterator.Next();
                    }
                }
            }
            catch (Exception) {
                _ErrorHappened = true;

                Windows.ApplicationModel.Resources.ResourceLoader loader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();
                _ErrorMessage = string.Format(loader.GetString("PackageDialog_FileExtractionError_Info"), Settings.Settings.DisplayName);
            }
            return null;
        }

        private async System.Threading.Tasks.Task<Windows.Storage.StorageFile> ExtractNonPDFDocFromPortFolio(PDFDoc doc, string fileName)
        {
            try
            {
                StorageFolder folder = await GetPDFPackageFolderAsync();
                NameTree files = NameTree.Find(doc.GetSDFDoc(), "EmbeddedFiles");
                if (files.IsValid())
                {
                    // Traverse the list of embedded files.
                    NameTreeIterator nameTreeIterator = files.GetIterator();
                    while (nameTreeIterator.HasNext())
                    {
                        String entryName = nameTreeIterator.Key().GetAsPDFText();
                        if (entryName.Equals(fileName, StringComparison.OrdinalIgnoreCase))
                        {
                            pdftron.PDF.FileSpec fileSpec = new pdftron.PDF.FileSpec(nameTreeIterator.Value());
                            pdftron.Filters.IFilter filter = fileSpec.GetFileData();
                            if (filter != null)
                            {
                                string newFileName = "tempfile." + GetExtension(fileName);
                                string newFullName = System.IO.Path.Combine(folder.Path, newFileName);
                                filter.WriteToFile(newFullName, false);
                                Windows.Storage.StorageFile file = await folder.GetFileAsync(newFileName);
                                return file;
                            }
                        }
                        nameTreeIterator.Next();
                    }
                }
            }
            catch (Exception)
            {
                _ErrorHappened = true;
                _ErrorMessage = "Sorry, " + Settings.Settings.DisplayName + " failed to extract the selected file.";
            }
            return null;
        }

        #endregion Construct Content


        #region Navigation

        private void PopFromStack()
        {
            ContentScroller.Content = _PackageNestingStack.Last();
            _PackageNestingStack.RemoveAt(_PackageNestingStack.Count - 1);
        }

        private void ItemButton_Click(object sender, RoutedEventArgs e)
        {
            Button button = sender as Button;
            PackageItem item = (PackageItem)button.Tag;
            if (item.IsPDF)
            {
                OpenPDF(item);
            }
            else
            {
                OpenNonPDF(item);
            }
        }

        private async void OpenPDF(PackageItem item)
        {
            PDFDoc newDoc = await ExtractPDFDocFromPortFolio(_PDFDoc, item.FileName);
            if (FileSelcted != null)
            {
                FileSelcted(newDoc, _ErrorHappened, _ErrorMessage);
            }
        }

        private async void OpenNonPDF(PackageItem item)
        {
            Windows.ApplicationModel.Resources.ResourceLoader loader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();
            

            Windows.UI.Popups.MessageDialog md = new Windows.UI.Popups.MessageDialog(string.Format(loader.GetString("PackageDialog_WrongFileType_Info"), Settings.Settings.DisplayName), loader.GetString("PackageDialog_WrongFileType_Title"));
            await CompleteReader.Utilities.MessageDialogHelper.ShowMessageDialogAsync(md);


            // The below would open the file in the default app for that file type. Unfortunately, this means that we can't delete the file later.
            // So if we did this, we would have to add a file save picker.

            //Windows.Storage.StorageFile file = await ExtractNonPDFDocFromPortFolio(_PDFDoc, item.FileName);
            //if (file != null)
            //{
            //    System.Diagnostics.Debug.WriteLine("Clicked Non PDF");
            //    await Windows.System.Launcher.LaunchFileAsync(file);
            //    System.Diagnostics.Debug.WriteLine("launched it");
            //    await System.Threading.Tasks.Task.Delay(10000);
            //    System.Diagnostics.Debug.WriteLine("viewing");
            //    await file.DeleteAsync();
            //    System.Diagnostics.Debug.WriteLine("killed it");
            //}
            //else
            //{
            //    System.Diagnostics.Debug.WriteLine("Clicked Non PDF but got error!");
            //}
        }

        #endregion Navigation




        #region Utility Functions


        /// <summary>
        /// Because the path might not be valid, we need to implement our own check for this
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private bool HasExtension(string fileName)
        {
            if (fileName.Contains('.'))
            {
                return true;
            }
            return false;
        }

        private string GetExtension(string fileName)
        {
            if (HasExtension(fileName))
            {
                string[] pathParts = fileName.Split('.');
                if (pathParts.Length > 0)
                {
                    return pathParts[pathParts.Length - 1];
                }
            }
            return null;
        }

        private async System.Threading.Tasks.Task<StorageFolder> GetPDFPackageFolderAsync()
        {
            StorageFolder folder = null;
            IStorageItem item = await Windows.Storage.ApplicationData.Current.TemporaryFolder.TryGetItemAsync("PDFPackageFolder");
            if (item == null)
            {
                folder = await Windows.Storage.ApplicationData.Current.TemporaryFolder.CreateFolderAsync("PDFPackageFolder", CreationCollisionOption.ReplaceExisting);
            }
            else
            {
                folder = item as StorageFolder;
            }
            return folder;
        }

        #endregion Utility Functions
    }
}
